home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 016a / gofer221.zip / CH10 < prev    next >
Text File  |  1991-11-20  |  20KB  |  595 lines

  1.  
  2.  
  3. Introduction to Gofer         10. INCREASING YOUR POWER OF EXPRESSION           
  4.  
  5.  
  6. 10. INCREASING YOUR POWER OF EXPRESSION
  7.  
  8. This section describes a number of useful extensions to the basic range
  9. of expressions used in the previous sections.  None of  these  add  any
  10. extra computational power to Gofer -- anything that can  be  done  with
  11. these constructs  could  also  be  done  with  the  constructs  already
  12. described.  They are however included in Gofer because they allow  many
  13. expressions and function definitions to be  written  more  clearly  and
  14. concisely than the equivalent expressions without these notations.
  15.  
  16. 10.1 Arithmetic sequences
  17. -------------------------
  18. A number of useful  lists  can  be  generated  using  the  notation  of
  19. arithmetic  sequences  (so  named  because  of  their   similarity   to
  20. arithmetic progressions in mathematics).  The following list summarises
  21. the four forms of sequence  expression  that  can  be  used  in  Gofer,
  22. together with their translation using the standard functions  enumFrom,
  23. enumFromTo, enumFromThen and enumFromThenTo:
  24.  
  25.     [ n .. ]         enumFrom n
  26.  
  27.                      Produces the (potentially infinite) list of values
  28.                      starting with the value of  n  and  increasing  in
  29.                      single steps.
  30.  
  31.                      e.g. [1..] = [1, 2, 3, 4, 5, 6, 7, 8, 9, etc...
  32.  
  33.     [ n .. m ]       enumFromTo n m
  34.  
  35.                      Produces the list of  elements  from  n  upto  and
  36.                      including m in single steps.  If m is less than  n
  37.                      then the list is empty.
  38.  
  39.                      e.g. [-3..3] = [-3, -2, -1, 0, 1, 2, 3]
  40.                           [1..1]  = [1]
  41.                           [9..0]  = []
  42.  
  43.     [ n, m .. ]      enumFromThen n m
  44.  
  45.                      Produces the (potentially infinite) list of values
  46.                      whose first two elements are given by the values n
  47.                      and m.  If m is greater than n then the  following
  48.                      elements of the list are increasing  in  steps  of
  49.                      the same size.  A similar result is obtained if  m
  50.                      is less than n  in  which  case  the  elements  of
  51.                      [n,m..] will be decreasing.  If n and m are  equal
  52.                      then [n,m..] is an infinite  list  in  which  each
  53.                      element is equal to n.
  54.  
  55.                      e.g. [1,3..] = [1, 3, 5, 7, 9, 11, 13, etc...
  56.                           [0,0..] = [0, 0, 0, 0, 0, 0, 0, etc...
  57.                           [5,4..] = [5, 4, 3, 2, 1, 0, -1, etc...
  58.  
  59.     [ n, n' .. m ]   enumFromThenTo n n' m
  60.  
  61.                      Produces the list of elements from  [n,n'..]  upto
  62.  
  63.  
  64.                                       37
  65.  
  66.  
  67.  
  68.  
  69. Introduction to Gofer         10.1 Arithmetic sequences                         
  70.  
  71.  
  72.                      the limit value m.   If  m  is  less  than  n  and
  73.                      [n,n'..] is increasing, or m is greater than n and
  74.                      [n,n'..] is decreasing then resulting list will be
  75.                      empty.
  76.  
  77.                      e.g. [1,3..12] = [1, 3, 5, 7, 9, 11]
  78.                           [0,0..10] = [0, 0, 0, 0, 0, 0, 0, etc...
  79.                           [5,4..1]  = [5, 4, 3, 2, 1]
  80.  
  81. In  the  standard  prelude,   the   functions   enumFrom,   enumFromTo,
  82. enumFromThen and enumFromThenTo are overloaded and may also be used  to
  83. enumerate lists of characters or floating point values:
  84.  
  85.     ? ['0'..'9'] ++ ['A'..'Z']
  86.     0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
  87.     (397 reductions, 542 cells)
  88.  
  89.     ? [1.2, 1.35 .. 2.00]
  90.     [1.2, 1.35, 1.5, 1.65, 1.8, 1.95]
  91.     (56 reductions, 133 cells)
  92.  
  93.     ?
  94.  
  95. Arithmetic sequences such as those described above play the  same  role
  96. in functional programming languages as the iterative  `for'  constructs
  97. in traditional imperative languages.  A good example  of  this  is  the
  98. example in section 4 used to calculate the sum of the integers  from  1
  99. upto 10 -- "sum [1..10]".   An  equivalent  program  in  an  imperative
  100. language might look something like (especially if you think of C!):
  101.  
  102.     int i;
  103.     int total=0;
  104.     for (i=1; i<=10; i++)
  105.         total = total + i;
  106.     return total;
  107.  
  108. The advantages of the functional notation in this case are clear:
  109.  
  110.    o  It is more compact.
  111.  
  112.    o  It separates the task of  generating  the  sequence  of  integers
  113.       [1..10] from the task of finding their sum.
  114.  
  115.    o  It does not require the declaration or use of auxiliary variables
  116.       such as "i" and "total" in the above.
  117.  
  118.  
  119. 10.2 List comprehensions
  120. -------------------------
  121. List comprehensions provide another very powerful and compact  notation
  122. for describing certain kinds of list expression.  The basic form  of  a
  123. list comprehension is:
  124.  
  125.                       [ <expr> | <qualifiers> ]
  126.  
  127. There are three kinds of qualifier that can be used in Gofer:
  128.  
  129.  
  130.                                       38
  131.  
  132.  
  133.  
  134.  
  135. Introduction to Gofer         10.2 List comprehensions                          
  136.  
  137.  
  138.   o  Generators: A qualifier of the form pat<-exp is  used  to  extract
  139.      each element that matches the pattern pat from the list exp in the
  140.      order that they elements appear in that list.  A simple example of
  141.      this is the expression [x*x | x<-[1..10]] which denotes  the  list
  142.      of the squares of the integers between  1  and  10  inclusive  and
  143.      evaluates to [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] as expected.
  144.  
  145.      Formally, we can define the meaning of a list comprehension with a
  146.      single generator by the equation:
  147.  
  148.           [ e | pat <- exp ]  =  loop exp
  149.                                  where loop []       = []
  150.                                        loop (pat:xs) = e : loop xs
  151.                                        loop (_:xs)   = loop xs
  152.  
  153.      If pat is an irrefutable pattern (for example,  a  variable)  then
  154.      this is equivalent to:
  155.  
  156.           [ e | pat <- exp ]  =  map f exp
  157.                                  where f pat = e
  158.  
  159.      The full definition is needed for those cases  where  the  pattern
  160.      pat may not match all of the elements in the list  exp.   This  is
  161.      the case in expressions such as [ y | (3,y)<-[(1,2),(3,4),(5,6)] ]
  162.      which evaluates to the singleton list [4].
  163.  
  164.   o  Filters: A boolean  valued  expression  may  also  be  used  as  a
  165.      qualifier in which case it is  often  called  a  filter.   We  can
  166.      define the meaning of a list comprehension with a single filter by
  167.      the equation:
  168.  
  169.             [ e | condition ]  =  if condition then [e] else []
  170.  
  171.      Whilst this form of list comprehension is occasionally  useful  as
  172.      it stands, it is more common to use filters  in  conjunction  with
  173.      generators as described below.
  174.  
  175.   o  Local definitions: A qualifier of the form pat=expr can be used to
  176.      introduce a local definition within  a  list  comprehension.   Its
  177.      meaning can be defined formally using the equation:
  178.  
  179.          [ e | pat = exp ]  =  [ let pat=exp in e ]
  180.  
  181.      As in the case of filters, local  definitions  are  more  commonly
  182.      used within lists of more than one qualifier as  described  below.
  183.      Particular care should be taken to distinguish  a  filter  of  the
  184.      form pat==expr from a local definition of the form pat=expr.
  185.  
  186.      [ASIDE: I originally suggested this form of qualifier in a message
  187.      sent to the Haskell mailing list, only to discover that a  similar
  188.      (and more comprehensive) suggestion had been made by Kevin Hammond
  189.      almost a year earlier.  There was a certain amount of  controversy
  190.      surrounding the choice of an appropriate syntax and semantics  for
  191.      the construct and consequently, this feature is not currently part
  192.      of the Haskell  standard.   The  syntax  and  semantics  above  is
  193.      implemented by Gofer in the hope  that  it  will  give  functional
  194.  
  195.  
  196.                                       39
  197.  
  198.  
  199.  
  200.  
  201. Introduction to Gofer         10.2 List comprehensions                          
  202.  
  203.  
  204.      programmers an opportunity to experiment  with  this  facility  in
  205.      their own programs.]
  206.  
  207. The real power of this notation is that it is possible to  use  several
  208. qualifiers, separated by commas on the right of the  vertical  bar  `|'
  209. symbol in a list comprehension.  Formally, if qs1 and qs2 are two  such
  210. lists of qualifiers,  then  we  can  define  the  meaning  of  multiple
  211. qualifiers using:
  212.  
  213.          [ e | qs1, qs2 ]  =  concat [ [ e | qs2 ] | qs1 ]
  214.  
  215. The  following  examples  illustrate  how  this  definition  works   in
  216. practice:
  217.  
  218.   o  Variables generated by later qualifiers  vary  more  quickly  than
  219.      those generated by earlier qualifiers:
  220.  
  221.          ? [ (x,y) | x<-[1..3], y<-[1..2] ]
  222.          [(1,1), (1,2), (2,1), (2,2), (3,1), (3,2)]
  223.          (107 reductions, 246 cells)
  224.          ?
  225.  
  226.   o  Later qualifiers may use the values generated by earlier ones:
  227.  
  228.          ? [ (x,y) | x<-[1..3], y<-[1..x]]
  229.          [(1,1), (2,1), (2,2), (3,1), (3,2), (3,3)]
  230.          (107 reductions, 246 cells)
  231.  
  232.          ? [ x | x<-[1..10], even x ]
  233.          [2, 4, 6, 8, 10]
  234.          (108 reductions, 171 cells)
  235.          ?
  236.  
  237.   o  Variables defined in later qualifiers  hide  those  introduced  by
  238.      earlier  ones.   The  following   expressions   are   valid   list
  239.      comprehensions, but this style of definition in  which  names  are
  240.      reused can result in programs which are difficult  to  understand,
  241.      and is not recommended:
  242.  
  243.          ? [ x | x<-[[1,2],[3,4]], x<-x ]
  244.          [1, 2, 3, 4]
  245.          (18 reductions, 53 cells)
  246.  
  247.          ? [ x | x<-[1,2], x<-[3,4] ]
  248.          [3, 4, 3, 4]
  249.          (18 reductions, 53 cells)
  250.          ?
  251.  
  252.   o  Changing  the  order  of  qualifiers  has  a  direct   effect   on
  253.      efficiency.  The following two examples produce the  same  result,
  254.      but the first uses more reductions and cells  because  it  repeats
  255.      the evaluation of "even x" for each possible value of "y".
  256.  
  257.          ? [ (x,y) | x<-[1..3], y<-[1..2], even x ]
  258.          [(2,1), (2,2)]
  259.          (110 reductions, 186 cells)
  260.  
  261.  
  262.                                       40
  263.  
  264.  
  265.  
  266.  
  267. Introduction to Gofer         10.2 List comprehensions                          
  268.  
  269.  
  270.          ? [ (x,y) | x<-[1..3], even x, y<-[1..2] ]
  271.          [(2,1), (2,2)]
  272.          (62 reductions, 118 cells)
  273.          ? 
  274.  
  275.      The following example illustrates a similar kind of behaviour with
  276.      local definitions; in the first case the expression  "fact  x"  is
  277.      evaluated twice for each possible value of "x", whilst the  second
  278.      expression uses a local definition to ensure that  the  evaluation
  279.      is not repeated:
  280.  
  281.          ? [ fact x + y | x<-[1..3], y<-[1..2] ]
  282.          [2, 3, 3, 4, 7, 8]
  283.          (246 reductions, 398 cells)
  284.  
  285.          ? [ factx + y | x<-[1..3], factx = fact x, y<-[1..2] ]
  286.          [2, 3, 3, 4, 7, 8]
  287.          (173 reductions, 294 cells)
  288.          ?
  289.  
  290.  
  291. 10.3 Lambda expressions
  292. ------------------------
  293. In addition to  named  function  definitions,  Gofer  also  allows  the
  294. definition and use of unnamed functions using a `lambda expression'  of
  295. the form:
  296.  
  297.                   \ <atomic patterns> -> <expr>
  298.  
  299. [ASIDE:  This  is  a  slight  generalisation  of  the  form  of  lambda
  300. expression  used  in  most   theoretical   treatments   of   functional
  301. programming and  dating  back  to  the  pioneering  work  of  logicians
  302. including Church, Curry and Haskell, from whom the programming language
  303. takes its name.  The `\' character used at the  beginning  of  a  Gofer
  304. lambda expression has been chosen for  its  resemblance  to  the  greek
  305. letter lambda that might be used if the standard character set  were  a
  306. little larger.]
  307.  
  308. This expression denotes a function taking a number of  parameters  (one
  309. for each pattern) and producing the result specified by the  expression
  310. to the right of the -> symbol.  For example, (\x->x*x)  represents  the
  311. function which takes a single integer argument  `x'  and  produces  the
  312. square of that number as its result.  Another example is the the lambda
  313. expression (\x y->x+y) which takes two integer  arguments  and  outputs
  314. their sum; this expression is in fact equivalent to the (+) operator:
  315.  
  316.     ? (\x y->x+y) 2 3
  317.     5
  318.     (3 reductions, 7 cells)
  319.     ?
  320.  
  321. A lambda expression of the form illustrated above is equivalent to  the
  322. following expression using a local definition:
  323.  
  324.       (let newName <atomic patterns> = <expr> in newName)
  325.  
  326.  
  327.  
  328.                                       41
  329.  
  330.  
  331.  
  332.  
  333. Introduction to Gofer         10.3 Lambda expressions                           
  334.  
  335.  
  336. where "newName" is a new variable name, chosen to avoid conflicts  with
  337. other variables that are already in use.  This name will be printed  if
  338. you enter an expression involving a lambda expression without supplying
  339. the full number of parameters for that function:
  340.  
  341.     ? (\x y -> x+y) 42
  342.     v117 42
  343.     (2 reductions, 14 cells)
  344.     ?
  345.  
  346. Lambda expressions  are  particularly  useful  for  certain  styles  of
  347. functional programming; an example of this  is  the  continuation-based
  348. approach to I/O described in section 12.
  349.  
  350.  
  351. 10.4 Case expressions
  352. ---------------------
  353. A case expression can be used to evaluate an expression and,  depending
  354. on the result, return one of a number of  possible  values.   As  such,
  355. case statements are a  straightforward  generalisation  of  conditional
  356. expressions.  Indeed, an expression of the form "if e then t else f" is
  357. in fact equivalent to the case expression:
  358.  
  359.                         case e of 
  360.                           True  -> t
  361.                           False -> f
  362.  
  363. In general, a case expression takes the form "case exp of  alts"  where
  364. exp  is  the  expression  to  be  evaluated  and  alts  is  a  list  of
  365. alternatives, each of which is of the form:
  366.  
  367.         pat -> rhs                    for a simple alternative
  368.  
  369.     or: pat | condition1 -> rhs1      using guard expressions as
  370.             | condition2 -> rhs2      described in section 9.2 for
  371.                   .                   function definitions
  372.                   .
  373.             | conditionn -> rhsn
  374.  
  375. In Gofer, a case expression of the form case e of alts  is  implemented
  376. by choosing a new function name "newName" as in  the  previous  section
  377. and  using  the  alternatives  in  alts  to  construct  an  appropriate
  378. definition for this function (essentially by replacing each `->' symbol
  379. with a `=' symbol).  The complete case expression is  then  treated  as
  380. being equivalent to the expression "newName e".  A  simple  example  of
  381. this is the "scanl" function whose definition in the standard prelude:
  382.  
  383.     scanl f q xs = q : (case xs of
  384.                         []   -> []
  385.                         x:xs -> scanl f (f q x) xs)
  386.  
  387. is equivalent to:
  388.  
  389.     scanl f q xs = q : scanl' xs
  390.                    where scanl' []     = []
  391.                          scanl' (x:xs) = scanl f (f q x) xs
  392.  
  393.  
  394.                                       42
  395.  
  396.  
  397.  
  398.  
  399. Introduction to Gofer         10.4 Case expressions                             
  400.  
  401.  
  402. This latter form is precisely the definition used in [1] (but using the
  403. name "scan" where Gofer uses "scanl").
  404.  
  405. Evaluating a case expression in which none of  the  alternatives  match
  406. the value  of  the  discriminant  results  in  an  error  such  as  the
  407. following:
  408.  
  409.     ? case [1,2] of [] -> "empty list"
  410.     {v117 [1, 2]}
  411.     (6 reductions, 31 cells)
  412.     ?
  413.  
  414. The function name "v117" which appears here is the name of the function
  415. which is used internally by Gofer  to  implement  the  case  expression
  416. whilst the expression "[1, 2]" gives the discriminant value which could
  417. not be matched.
  418.  
  419. By combining case expressions with the lambda expressions introduced in
  420. the previous section, any function declaration can be translated into a
  421. single equation of the form <functionName> = <expr>.  For example,  the
  422. standard function "map" whose definition is usually written as:
  423.  
  424.     map f []     = []
  425.     map f (x:xs) = f x : map f xs
  426.  
  427. can also be defined by the equation:
  428.  
  429.     map = \f xs -> case xs of
  430.                      []     -> []
  431.                      (y:ys) -> f y : map f ys
  432.  
  433. This kind  of  translation  is  used  in  the  implementation  of  many
  434. functional programming languages, including Gofer.   See  Simon  Peyton
  435. Jones book [2] for more details of this.
  436.  
  437.  
  438. 10.5 Operator sections
  439. ----------------------
  440. As we have seen, most functions in Gofer taking more than one  argument
  441. are treated as a function of a  single  argument,  whose  result  is  a
  442. function which can then be applied to the  remaining  arguments.   Thus
  443. "(+) 1" denotes the function which takes an integer  argument  "n"  and
  444. returns the integer value "1+n".   Functions  of  this  kind  involving
  445. operator symbols are sufficiently common that Gofer provides a  special
  446. syntax for them.  Using e to denote an atomic expression and the symbol
  447. "*" to represent an arbitrary infix operator, there are functions (e *)
  448. and (* e), known as `sections of the operator (*)' defined by:
  449.  
  450.                   (e *) x  = e * x
  451.                   (* e) x  = x * e
  452.  
  453. or, using lambda expressions as introduced in section 10.3:
  454.  
  455.                   (e *)    =  \x -> e * x
  456.                   (* e)    =  \x -> x * e
  457.  
  458.  
  459.  
  460.                                       43
  461.  
  462.  
  463.  
  464.  
  465. Introduction to Gofer         10.5 Operator sections                            
  466.  
  467.  
  468. For example: (1+)   is the successor function which returns the value
  469.                     of its argument plus 1,
  470.              (1.0/) is the reciprocal function,
  471.              (/2)   is the halving function,
  472.              (:[])  is the function which maps any value to the
  473.                     singleton list containing that element.
  474.  
  475. In Gofer, the expressions "(e *)" and "(* e)" are actually  treated  as
  476. abbreviations for "(*) e" and "flip (*) e" respectively,  where  "flip"
  477. is the function defined by:
  478.  
  479.      flip        :: (a -> b -> c) -> b -> a -> c
  480.      flip  f x y  =  f y x
  481.  
  482. There is an important special case which occurs with an  expression  of
  483. the form (- e); this is interpreted  as  "negate  e"  and  not  as  the
  484. section which subtracts the value of "e" from its argument.  The latter
  485. function can be written as the section (+ (- e))  or  as  "subtract  e"
  486. where "subtract" is the function defined in the standard prelude using:
  487.  
  488.     subtract = flip (-)
  489.  
  490.  
  491. 10.6 Explicitly typed expressions
  492. ----------------------------------
  493. As described in section 9.12, it is often useful to be able to  declare
  494. the type of a variable defined in a function or pattern  binding.   For
  495. much the same reasons, Gofer allows expressions of the form:
  496.  
  497.                          <expr> :: <type>
  498.  
  499. so that the type of an expression can be  specified  explicitly.   Note
  500. that the :t command can be used  to  find  the  type  of  a  particular
  501. expression that is inferred by Gofer:
  502.  
  503.     ? :t  \x -> [x]
  504.     \x -> [x] :: a -> [a]
  505.  
  506.     ? :t  sum . map length
  507.     sum . map length :: [[a]] -> Int
  508.  
  509.     ? 
  510.  
  511. The types inferred in each case can be modified by  including  explicit
  512. types in these expressions:
  513.  
  514.     ? :t  (\x -> [x]) :: Char -> String
  515.     \x -> [x] :: Char -> String
  516.  
  517.     ? :t  sum . map (length :: String -> Int)
  518.     sum . map length :: [String] -> Int
  519.  
  520.     ?
  521.  
  522. Note that an error occurs if the type declared in an  explicitly  typed
  523. expression is not compatible with the type inferred by Gofer:
  524.  
  525.  
  526.                                       44
  527.  
  528.  
  529.  
  530.  
  531. Introduction to Gofer         10.6 Explicitly typed expressions                 
  532.  
  533.  
  534.     ? :t (\x -> [x]) :: Int -> a
  535.     ERROR: Declared type too general
  536.     *** Expression    : \x -> [x]
  537.     *** Declared type : Int -> a
  538.     *** Inferred type : Int -> [Int]
  539.  
  540.     ?
  541.  
  542. Explicitly typed expressions  are  most  commonly  used  together  with
  543. overloaded functions and values as described in section 14.
  544.  
  545.  
  546.  
  547.  
  548.  
  549.  
  550.  
  551.  
  552.  
  553.  
  554.  
  555.  
  556.  
  557.  
  558.  
  559.  
  560.  
  561.  
  562.  
  563.  
  564.  
  565.  
  566.  
  567.  
  568.  
  569.  
  570.  
  571.  
  572.  
  573.  
  574.  
  575.  
  576.  
  577.  
  578.  
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587.  
  588.  
  589.  
  590.  
  591.  
  592.                                       45
  593.  
  594.  
  595.